package com.iwhalecloud.bss.kite.cucc.web.controller.scene;

import com.iwhalecloud.bss.kite.client.dto.DataResult;
import com.iwhalecloud.bss.kite.common.constant.ErrorConsts;
import com.iwhalecloud.bss.kite.common.constant.ExtParamConsts;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.unicode.UnicodeOperTypeKite;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteMapUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.client.api.pay.IPaymentService;
import com.iwhalecloud.bss.kite.cucc.client.api.scene.ICuccSceneService;
import com.iwhalecloud.bss.kite.cucc.client.dto.pay.ResaleOrderRequest;
import com.iwhalecloud.bss.kite.cucc.client.dto.pos.KitePosDTO;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalKeyConsts;
import com.iwhalecloud.bss.kite.cucc.common.constant.LocalServiceOfferConsts;
import com.iwhalecloud.bss.kite.cucc.dataservice.cache.ResaleOrderInfoCache;
import com.iwhalecloud.bss.kite.cucc.service.context.CuccServiceContext;
import com.iwhalecloud.bss.kite.cucc.web.service.ISceneService;
import com.iwhalecloud.bss.kite.cucc.web.service.accept.vo.InitSceneVO;
import com.iwhalecloud.bss.kite.dataservice.cache.DcPublicCache;
import com.iwhalecloud.bss.kite.dataservice.cache.OfferCache;
import com.iwhalecloud.bss.kite.dataservice.entity.spec.Offer;
import com.iwhalecloud.bss.kite.dataservice.util.GeneralSwitchUtils;
import com.iwhalecloud.bss.kite.manager.api.IOperateSceneInstService;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.inst.KiteProdInst;
import com.iwhalecloud.bss.kite.manager.inst.KiteSceneInst;
import com.iwhalecloud.bss.kite.manager.transaction.KiteTransactional;
import com.iwhalecloud.bss.kite.manager.util.KiteTransactionUtils;
import com.iwhalecloud.bss.kite.web.context.KiteWebContext;
import com.iwhalecloud.bss.kite.web.service.accept.vo.PageNavigationVO;
import com.ztesoft.bss.common.bo.UserInfo;
import com.ztesoft.bss.common.util.ContextUtil;
import com.ztesoft.bss.common.util.SpringUtil;
import com.ztesoft.common.logger.api.ZLogger;
import com.ztesoft.common.logger.factory.ZLoggerFactory;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/paySceneInit")
public class PaySceneInitController {

    private static final ZLogger LOGGER = ZLoggerFactory.getLogger(PaySceneInitController.class, KeyConsts.LOG_MODULE);

    @Autowired
    private IOperateSceneInstService operateSceneInstService;

    @Autowired
    private IQuerySceneInstService querySceneInstService;

    @Autowired
    private ISceneService sceneService;

    @Autowired
    private ICuccSceneService cuccSceneService;

    @Autowired
    private IPaymentService paymentService;

    @KiteTransactional
    @ApiOperation(value = "趸交根据订单ID创建支付详情场景", notes = "趸交根据订单ID创建支付详情场景")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "orderId", value = "订单ID", required = true),
        @ApiImplicitParam(name = "bizType", value = "订单ID", required = true)
    })
    @GetMapping("/initPayOrderDetailScene")
    public DataResult<InitSceneVO> initPayOrderDetailScene(@RequestParam(required = true) String orderId, @RequestParam(required = true) String bizType) {
        String cartId = this.cuccSceneService.getCartIdFromES().getResultObject();
        String serviceOfferId = DcPublicCache.getPCode("20201130001", bizType);
        if (KiteStringUtils.isEmpty(serviceOfferId)) {
            serviceOfferId = bizType;
        }
        String sceneInstId = "";
        if (GeneralSwitchUtils.isSwitchOpened("INIT_WITH_MUTIL_THREAD")) {
            CuccServiceContext.setIsCallInfForInitAttr(Boolean.FALSE);
            String staffId = ContextUtil.getUserId().toString();
            String lanId = ContextUtil.getLandId();
            String regionId = ContextUtil.getLoginInfo().getUserInfo().getPostRegionId().toString();

            Map<String, Object> dataMap = this.cuccSceneService.getOfferSceneDataByOrderDetailInfo(orderId, serviceOfferId,
                KeyConsts.KITE_SCENE_INST_OPER_TYPE_1000, "", "", staffId, lanId, regionId).getResultObject();

            KitePosDTO kitePosDTO = (KitePosDTO) KiteMapUtils.getObject(dataMap, "kitePosDTO");
            this.sceneService.initContext(kitePosDTO.getCustomer());

            sceneInstId = this.cuccSceneService
                .initModifyScene(serviceOfferId, KeyConsts.KITE_SCENE_INST_OPER_TYPE_1000, LocalKeyConsts.ASK_SOURCE_ORDER,
                    KiteWebContext.getContext().getCustId(), KiteWebContext.getContext().getCust().getCustName(), staffId,
                    lanId, regionId, kitePosDTO)
                .getResultObject();

            KiteWebContext.addAndUpdateSceneInstId(sceneInstId);
            Map<String, Object> orderInfo = (Map<String, Object>) KiteMapUtils.getObject(dataMap, "orderInfo");
            this.cuccSceneService.initDetailSceneAttrValues(sceneInstId, serviceOfferId,
                KeyConsts.KITE_SCENE_INST_OPER_TYPE_1000, cartId, KiteWebContext.getContext().getCustId(), staffId, orderId, "",
                orderInfo, kitePosDTO, null);
        } else {
            sceneInstId = this.sceneService
                .createOfferSceneByOrderDetailInfo(orderId, serviceOfferId, "", "",
                    ContextUtil.getUserId().toString(), ContextUtil.getLandId(),
                    ContextUtil.getLoginInfo().getUserInfo().getPostRegionId().toString(),
                    KeyConsts.KITE_SCENE_INST_OPER_TYPE_1000).getResultObject();
        }
        KiteSceneInst kiteSceneInst = this.querySceneInstService
            .getSceneInst(sceneInstId, KiteWebContext.getContext().getCustId());

        this.sceneService.setSceneInstId(sceneInstId, cartId, UnicodeOperTypeKite.OPERTYPE_1001);
        // 支付详情打标
        this.operateSceneInstService.putExtParameter(sceneInstId, "PAY_DETAIL_FLAG", "T");
        this.operateSceneInstService.putExtParameter(sceneInstId, "PAY_ORDER_ID", orderId);

        String offerId = querySceneInstService
            .getKiteInst(KiteWebContext.getContext().getCustId(), kiteSceneInst.getRootInstType(),
                kiteSceneInst.getRootInstId()).getSpecId();
        Offer offer = OfferCache.get(offerId);
        String cateId = offer.getCateId();
        PageNavigationVO pageNavigationVO = SpringUtil.getBean(SceneController.class)
            .getPageNavigation(serviceOfferId, offer.getOfferType(), offerId, sceneInstId, null, null)
            .getResultObject();
        if (pageNavigationVO == null) {
            ErrorConsts.BUSI_COMMON_ERROR.throwOut("未配置支付详情页面流程");
        }
        return ErrorConsts.SUCCESS.getResult(new InitSceneVO(offerId, sceneInstId, pageNavigationVO, cateId, KiteWebContext.getContext().getCustId()));
    }

    @KiteTransactional
    @ApiOperation(value = "趸交返销场景初始化", notes = "趸交返销场景初始化")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "resaleOrderRequest", value = "返销场景初始化请求对象", required = true)
    })
    @PostMapping("/initResaleScene")
    public DataResult<InitSceneVO> initResaleScene(@RequestBody ResaleOrderRequest resaleOrderRequest) {
        Assert.notNull(resaleOrderRequest.getOrderId(), "必传参数为空！");
        Assert.notNull(resaleOrderRequest.getSerialNumber(), "必传参数为空！");
        Offer offer = OfferCache.get(resaleOrderRequest.getGoodsCode());
        if (Objects.isNull(offer)) {
            ErrorConsts.BUSI_COMMON_ERROR.throwOut("商品不存在");
        }
        this.supplyRequestInfo(resaleOrderRequest);
        // 竣工订单信息
        KitePosDTO orderKitePosDTO = this.getOrderInfo(resaleOrderRequest);
        // 初始化客户信息
        this.sceneService.initContext(orderKitePosDTO.getCustomer());
        resaleOrderRequest.setCustId(KiteWebContext.getContext().getCustId());
        resaleOrderRequest.setCustName(KiteWebContext.getContext().getCust().getCustName());
        // 用户详情
        KitePosDTO userKitePosDTO = this.getUserInfo(resaleOrderRequest, offer);
        // 校验能否进行返销
        paymentService.resaleCheck(resaleOrderRequest, orderKitePosDTO, userKitePosDTO);
        // 创建返销场景
        String sceneInstId = cuccSceneService.createResaleScene(resaleOrderRequest, userKitePosDTO).getResultObject();
        KiteWebContext.addAndUpdateSceneInstId(sceneInstId);
        // 初始化场景数据
        this.dealSceneAttrValue(sceneInstId, resaleOrderRequest, userKitePosDTO);
        // 页面流信息
        PageNavigationVO pageNavigationVO = this.getNavigation(sceneInstId, resaleOrderRequest, offer);
        return ErrorConsts.SUCCESS.getResult(new InitSceneVO(offer.getOfferId(), sceneInstId, pageNavigationVO, offer.getCateId(), resaleOrderRequest.getCustId()));
    }

    private void supplyRequestInfo(ResaleOrderRequest resaleOrderRequest) {
        UserInfo userInfo = ContextUtil.getLoginInfo().getUserInfo();
        resaleOrderRequest.setStaffId(ContextUtil.getUserId().toString());
        resaleOrderRequest.setLanId(ContextUtil.getLandId());
        resaleOrderRequest.setStaffCode(KiteMapUtils.getString(userInfo.getExtParams(), "account"));
        resaleOrderRequest.setRegionId(userInfo.getPostRegionId().toString());
        resaleOrderRequest.setProvinceId(userInfo.getPostProvinceNbr());
        resaleOrderRequest.setCartId(cuccSceneService.getCartIdFromES().getResultObject());
        // 趸交返销操作码1070
        resaleOrderRequest.setServiceOfferId(LocalServiceOfferConsts.SERVICE_OFFER_RESALE);
    }

    private KitePosDTO getOrderInfo(ResaleOrderRequest resaleOrderRequest) {
        StopWatch sw = new StopWatch("返销场景开始");
        sw.start("返销场景-根据订单号获取订单详情");
        KitePosDTO orderKitePosDTO = ResaleOrderInfoCache.get(resaleOrderRequest.getOrderId());
        if (Objects.isNull(orderKitePosDTO)) {
            Map<String, Object> dataMap = this.cuccSceneService.getOfferSceneDataByOrderDetailInfo(resaleOrderRequest.getOrderId(), resaleOrderRequest.getServiceOfferId(),
                KeyConsts.KITE_SCENE_INST_OPER_TYPE_1000, "", "", resaleOrderRequest.getStaffId(), resaleOrderRequest.getLanId(), resaleOrderRequest.getRegionId()).getResultObject();
            orderKitePosDTO = (KitePosDTO) KiteMapUtils.getObject(dataMap, "kitePosDTO");
            ResaleOrderInfoCache.getInst().defaultPut(resaleOrderRequest.getOrderId(), orderKitePosDTO);
        }
        if (Objects.nonNull(orderKitePosDTO) && KiteListUtils.isNotEmpty(orderKitePosDTO.getUsers())) {
            orderKitePosDTO.getUsers().forEach(user -> {
                if (KiteStringUtils.isEqual(resaleOrderRequest.getSerialNumber(), user.getSerialNumber())) {
                    resaleOrderRequest.setUserId(user.getUserId());
                }
            });
        }
        sw.stop();
        LOGGER.info(sw.prettyPrint());
        return orderKitePosDTO;
    }

    private KitePosDTO getUserInfo(ResaleOrderRequest resaleOrderRequest, Offer offer) {
        boolean hasMember = false;
        if (KiteStringUtils.isEqual(offer.getOfferType(), KeyConsts.OFFER_TYPE_15)) {
            // 如果是融合要拼接成员
            hasMember = true;
        }
        StopWatch sw = new StopWatch("返销场景获取用户详情");
        sw.start("返销场景-根据业务号码获取用户详情");
        Map<String, Object> kitePosDtoMap = cuccSceneService.getAllChangeOriginOrder(hasMember, null, resaleOrderRequest.getGoodsCode(),
            resaleOrderRequest.getCustId(), resaleOrderRequest.getSerialNumber(), resaleOrderRequest.getProvinceId(), resaleOrderRequest.getLanId(), resaleOrderRequest.getStaffCode(), resaleOrderRequest.getUserId()).getResultObject();
        sw.stop();
        KitePosDTO userKitePosDTO = (KitePosDTO) KiteMapUtils.getObject(kitePosDtoMap, "kitePosDTO");
        LOGGER.info(sw.prettyPrint());
        return userKitePosDTO;
    }

    private void dealSceneAttrValue(String sceneInstId, ResaleOrderRequest resaleOrderRequest, KitePosDTO userKitePosDTO) {
        // 初始化属性值
        cuccSceneService.initSceneAttrValues(sceneInstId, null, resaleOrderRequest.getCustId(), resaleOrderRequest.getStaffId(), userKitePosDTO);
        String kiteContextId = KiteWebContext.getKiteContextId();
        CompletableFuture.runAsync(() -> {
            KiteWebContext.setKiteContextId(kiteContextId);
            KiteTransactionUtils.beginTransaction();
            try {
                this.cuccSceneService.initMoreSceneAttrValues(sceneInstId, resaleOrderRequest.getCustId(), resaleOrderRequest.getStaffCode(), resaleOrderRequest.getProvinceId(), userKitePosDTO);
            }
            catch (Exception e) {
                LOGGER.error(ErrorConsts.SYSTEM_ERROR.getErrorCode(), e, ErrorConsts.SYSTEM_ERROR.getMsg());
            }
            finally {
                KiteTransactionUtils.commit();
                ContextUtil.removeThreadLocal();
            }
        });
        operateSceneInstService.putExtParameter(sceneInstId, ExtParamConsts.EXT_PARAM_PROD_INST_IDS,
            querySceneInstService.listProdInsts(sceneInstId).stream().map(KiteProdInst::getProdInstId).collect(Collectors.toList()));
        // 返销打标
        operateSceneInstService.putExtParameter(sceneInstId, "SCENE_RESALE", "resale");
        // 保存返销订单号
        operateSceneInstService.putExtParameter(sceneInstId, "RESALE_ORDER_ID", resaleOrderRequest.getOrderId());
    }

    private PageNavigationVO getNavigation(String sceneInstId, ResaleOrderRequest resaleOrderRequest, Offer offer) {
        String offerId = offer.getOfferId();
        PageNavigationVO pageNavigationVO = SpringUtil.getBean(SceneController.class)
            .getPageNavigation(resaleOrderRequest.getServiceOfferId(), offer.getOfferType(), offerId, sceneInstId, null, null)
            .getResultObject();
        if (pageNavigationVO == null) {
            ErrorConsts.BUSI_COMMON_ERROR.throwOut("未配置返销页面流程");
        }
        return pageNavigationVO;
    }
}
